Controlling the 3.5 Drive Hardware on the Apple IIGS
By Neil Parker
Copyright (c) 1991 Apple Users' Group, Sydney
Republished from Applecations, a publication of the Apple Users' Group, Sydney, Australia.
A real live working program!
The program listed below was written to illustrate the steps necessary to control the hardware of the 3.5 Drive from your own programs, without the use of the operating system or the firmware. It is essentially a 3.5-inch version of the DUMP program by Don Worth which was printed in _Beneath_Apple_DOS_. It will read a track from a 3.5-inch disk into your Apple's memory, in its raw, encoded form.
Included below are a commented source code listing and a hex dump suitable for typing directly into the System Monitor (or capturing into a text file and EXECing).
Instructions:
First, boot DOS 3.3 or ProDOS 8. DUMP3.5 should be compatible with either operating system. If you booted ProDOS, get into BASIC.SYSTEM. When you see the ] prompt, type "BLOAD DUMP3.5", and then "CALL-151". Store the number of the track you wish to examine in memory location 6, and the disk side you wish to examine (0 for the lower side, anything else for the upper side) in location 7. Put the disk to be examined in Drive 1, and type "900G". The raw track data will then be found in memory locations $1000 through $7FFF (this buffer is much longer than an actual track, so the data will most likely be repeated several times in the buffer).
For example,
]BLOAD DUMP3.5 (Load the program)
]CALL-151 (Enter the Monitor)
*6:20 (Select track $20)
*7:1 (Select upper side)
*900G (Run DUMP3.5 (don't forget to insert the disk first))
*1000.10FF (Examine the first 256 bytes of the track)
The usual Dire Warnings apply: I make no guarantees whatsoever for this program. I have tested it, and it seems to work on mycomputer, but I recommend using it ONLY on expendable disks, and ONLY with the write-protect hole open. I assume no responsibility for any damage which may result from the use or misuse of this program.
Be especially careful if you enter either the assembly listing or the hex dump by hand--the slightest typographical error could turn a benign tool into a malevolent disk-eating monster.
I hope this program helps clarify the disk access process. If there is enough interest in an explanation of how to interpret what it accesses, it might be possible to talk me into writing up an explanation of the block encoding process. (I recommend first reading "Beneath Apple DOS" (if you can find a copy), and also the SmartPort chapter of the Firmware Reference.)
;*********************************************************** **************
; DUMP3.5--Dump a track of a 3.5-inch disk to memory. (IIGS only)
;
; By Neil Parker--inspired by Don Worth's DUMP program from "Beneath
; Apple DOS"
;
; Inputs: $06 = Track to be dumped
; $07 = Side to be dumped (0=lower side, non-0=upper side)
; Outputs: $1000-$7FFF = raw track data
;
; Example:
; *6:20 1 (Select track $20, upper side)
; *900G (Run DUMP3.5)
; *1000.10FF (Examine part of the track)
;*********************************************************** **************
ORG $900
TRACK EQU 6 ;Track number
SIDE EQU 7 ;Side number
PTR EQU 8
BUFFER EQU $1000 ;Start address for track data
SLTROMSEL EQU $C02D ;Select internal/external ROMs for slots
DISKREG EQU $C031 ;Select 3.5/5.25 drive, control SEL line
CYAREG EQU $C036 ;System speed and motor-on-detect bits
CA0 EQU $C0E0 ;Phase 0, 3.5 drive control
CA1 EQU $C0E2 ;Phase 1, 3.5 drive control
CA2 EQU $C0E4 ;Phase 2, 3.5 drive control
LSTRB EQU $C0E6 ;Phase 3, control strobe
ENABLE EQU $C0E8 ;Turn drive off/on
SELECT EQU $C0EA ;Select drive 1/2
Q6 EQU $C0EC
Q7 EQU $C0EE
;
LDA SLTROMSEL ;Get slot 6 status,
PHA ;save it,
AND #$BF ;force internal ROM+I/O for Slot 6
STA SLTROMSEL
LDA CA0 ;Clear disk I/O latches
LDA CA1
LDA CA2
LDA LSTRB
LDA ENABLE ;Insure that drive is off
LDA SELECT ;Select drive 1
LDA Q6 ;Set IWM for reading (a "safe" state)
LDA Q7
LDA #$F ;Configure IWM for 3.5 access
JSR SELIWM
LDA DISKREG ;Save old DISKREG
PHA
ORA #$40 ;Select 3.5 drive
STA DISKREG
LDA ENABLE+1 ;Turn drive on
LDA #2 ;Is there a disk in the drive?
JSR SEL35
JSR TEST35
BPL THERE ;If so, read
JMP DONE ;otherwise quit
THERE LDA #8 ;Turn motor on
JSR SEL35
JSR TRIG35
LDA #1 ;Set step direction=outward
JSR SEL35
JSR TRIG35
TSTTRK0 LDA #$A ;Are we at track 0 yet?
JSR SEL35
JSR TEST35
BPL ATTRK0 ;If so, go read
LDA #4 ;otherwise do a step
JSR SEL35
JSR TRIG35
SEEKING0 JSR TEST35 ;Step still in progress?
BPL SEEKING0 ;If so, loop until step done
BMI TSTTRK0 ;otherwise go see if we're at track 0 yet
ATTRK0 LDX TRACK ;What track did the user want?
BEQ DUMP ;If track 0, we're already there--go read
LDA #0 ;else set step direction=inward
JSR SEL35
JSR TRIG35
SEEK LDA #4 ;Do a step
JSR SEL35
JSR TRIG35
SEEKING JSR TEST35 ;Step still in progress?
BPL SEEKING ;If so, loop until step done
DEX ;otherwise see if we've stepped enough yet
BNE SEEK ;If not, go step again
DUMP LDA #$B ;Disk ready for reading yet?
JSR SEL35
READYT JSR TEST35
BMI READYT ;Loop until disk ready
LDA SIDE ;What side did the user want?
BEQ SIDE1 ;If 0, set lower side
LDA #3 ;else set upper side
BNE SETSIDE
SIDE1 LDA #1
SETSIDE JSR SEL35
JSR TEST35
PHP ;Save interrupt status
SEI ;Don't let anything interrupt us
LDA CYAREG ;Save old system speed
PHA
AND #$FB ;Set speed=fast
ORA #$80
STA CYAREG
LDA #<BUFFER ;Initialize read buffer
STA PTR ;(NOTE: For DOS TOOL KIT or EDASM assembler,
LDA #>BUFFER ;change #> to #< and #< to #>.)
STA PTR+1
LDY #0
DUMPLP LDA Q6 ;Read a byte
BPL DUMPLP ;Loop until we have a valid byte
STA (PTR),Y ;Store byte in buffer
INC PTR ;Advance buffer pointer
BNE DUMPLP
INC PTR+1
LDA PTR+1 ;Buffer full yet?
CMP #$80
BCC DUMPLP ;If not, go read some more
PLA ;Done. Restore system speed
STA CYAREG
PLP ;Restore interrupt status
LDA #9 ;Turn motor off
JSR SEL35
JSR TRIG35
DONE LDA ENABLE ;Turn drive off
LDA CA0 ;Clear disk I/O latches
LDA CA1
LDA CA2
LDA LSTRB
PLA ;Restore old DISKREG value
STA DISKREG
LDA #0 ;Configure IWM for 5.25 access
JSR SELIWM
PLA ;Restore original slot configuration
STA SLTROMSEL
RTS ;Amen.
;
;Subroutine to select 3.5 drive status/control registers
;Enter with accumulator=desired status:
; Bit 0=CA2 status
; Bit 1=SEL status
; Bit 2=CA0 status
; Bit 3=CA1 status
;
SEL35 BIT CA0
BIT CA1+1
BIT LSTRB
BIT CA2
LSR ;If bit 0 set, turn on CA2
BCC S35A
BIT CA2+1
S35A LSR ;If bit 1 set, turn on SEL
PHA
LDA DISKREG
AND #$7F
BCC S35B
ORA #$80
S35B STA DISKREG
PLA
LSR ;If bit 2 set, turn on CA0
BCC S35C
BIT CA0+1
S35C LSR ;If bit 3 set, turn on CA1
BCS S35D
BIT CA1
S35D RTS
;
;Subroutine to read the status of the 3.5 drive
;First call SEL35 to select register to examine
;Result is in processor N (negative) flag
;
TEST35 BIT Q6+1
BIT Q7
RTS
;
;Subroutine to perform a 3.5 drive control function
;First call SEL35 to select function to be performed
;
TRIG35 BIT LSTRB+1
BIT LSTRB
RTS
;
;Subroutine to configure the IWM chip
;Before calling, make sure drive is OFF!
;Call with accumulator=desired Mode Register value
; A=$00 for 5.25 drive
; A=$0F for 3.5 drive
;
SELIWM TAY
BIT Q6+1 ;Prepare to access Mode & Status Regs.
JMP SELIWM2 ;First see if it's already set like we want it
SELIWM1 TYA
STA Q7+1 ;Try writing to Mode Reg.
SELIWM2 TYA
EOR Q7 ;Compare input to Status Reg.
AND #$1F
BNE SELIWM1 ;If not the same, try writing again
BIT Q6 ;else prepare IWM for data
RTS
Here is the hext dump corresponding to the above assembler listing.
This can be entered by hand into the Monitor, or you can capture it into
a text file, put "CALL-151" at the beginning and "3D0G" and "BSAVE
DUMP3.5,A$900,L$145" at the end and EXEC it to create the program.
900:AD 2D C0 48 29 BF 8D 2D C0 AD E0 C0 AD E2 C0 AD
910:E4 C0 AD E6 C0 AD E8 C0 AD EA C0 AD EC C0 AD EE
920:C0 A9 0F 20 2E 0A AD 31 C0 48 09 40 8D 31 C0 AD
930:E9 C0 A9 02 20 F2 09 20 20 0A 10 03 4C D5 09 A9
940:08 20 F2 09 20 27 0A A9 01 20 F2 09 20 27 0A A9
950:0A 20 F2 09 20 20 0A 10 0F A9 04 20 F2 09 20 27
960:0A 20 20 0A 10 FB 30 E7 A6 06 F0 18 A9 00 20 F2
970:09 20 27 0A A9 04 20 F2 09 20 27 0A 20 20 0A 10
980:FB CA D0 F0 A9 0B 20 F2 09 20 20 0A 30 FB A5 07
990:F0 04 A9 03 D0 02 A9 01 20 F2 09 20 20 0A 08 78
9A0:AD 36 C0 48 29 FB 09 80 8D 36 C0 A9 00 85 08 A9
9B0:10 85 09 A0 00 AD EC C0 10 FB 91 08 E6 08 D0 F5
9C0:E6 09 A5 09 C9 80 90 ED 68 8D 36 C0 28 A9 09 20
9D0:F2 09 20 27 0A AD E8 C0 AD E0 C0 AD E2 C0 AD E4
9E0:C0 AD E6 C0 68 8D 31 C0 A9 00 20 2E 0A 68 8D 2D
9F0:C0 60 2C E0 C0 2C E3 C0 2C E6 C0 2C E4 C0 4A 90
A00:03 2C E5 C0 4A 48 AD 31 C0 29 7F 90 02 09 80 8D
A10:31 C0 68 4A 90 03 2C E1 C0 4A B0 03 2C E2 C0 60
A20:2C ED C0 2C EE C0 60 2C E7 C0 2C E6 C0 60 A8 2C
A30:ED C0 4C 39 0A 98 8D EF C0 98 4D EE C0 29 1F D0
A40:F4 2C EC C0 60

THIS CONTENT COPYRIGHT © 2007, APPLE MACINTOSH USERS' GROUP, SYDNEY
Permission has been obtained to make this material available on the Internet.

Permission is hereby granted for non-profit user groups to republish this content.
PLEASE CREDIT THE AUTHOR AND THE SOURCE: Applecations, publication of the Apple Users' Group, Sydney, Australia

THIS PAGE COPYRIGHT © 2007, ANDREW ROUGHAN